﻿using Furion;
using HiSport.Core.Const;
using HiSport.Core.Entities;
using HiSport.Core;
using SqlSugar;
using System;
using System.Collections.Concurrent;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using NewLife.Caching;
using HiSport.Core.Enum;

namespace HiSport.SqlSugar
{

    public static class SqlSugarFilter
    {
        /// <summary>
        /// 缓存全局查询过滤器（内存缓存）
        /// </summary>
        private static readonly ICache _cache = Cache.Default;

        /// <summary>
        /// 删除用户机构缓存
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="dbConfigId"></param>
        public static void DeleteUserOrgCache(long userId, string dbConfigId)
        {
            // 删除用户机构集合缓存
            App.GetService<SysCacheService>().Remove($"{CacheConst.KeyUserOrg}{userId}");
            // 删除用户机构（数据范围）过滤器缓存
            _cache.Remove($"db:{dbConfigId}:orgList:{userId}");
        }

        /// <summary>
        /// 配置用户机构集合过滤器
        /// </summary>
        public static void SetOrgEntityFilter(SqlSugarScopeProvider db)
        {
            // 若仅本人数据，则直接返回
            if (SetDataScopeFilter(db) == (int)DataScopeEnum.Self) return;

            var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value;
            if (string.IsNullOrWhiteSpace(userId)) return;

            // 配置用户机构集合缓存
            var cacheKey = $"db:{db.CurrentConnectionConfig.ConfigId}:orgList:{userId}";
            var orgFilter = _cache.Get<ConcurrentDictionary<Type, LambdaExpression>>(cacheKey);
            if (orgFilter == null)
            {
                // 获取用户所属机构
                var orgIds = 0; //App.GetService<SysOrgService>().GetUserOrgIdList().GetAwaiter().GetResult();
                //if (orgIds == null || orgIds.Count == 0) return;

                // 获取业务实体数据表
                var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
                    && u.IsSubclassOf(typeof(EntityBaseData)));
                if (!entityTypes.Any()) return;

                orgFilter = new ConcurrentDictionary<Type, LambdaExpression>();
                foreach (var entityType in entityTypes)
                {
                    // 排除非当前数据库实体
                    var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
                    if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()))
                        continue;

                    var lambda = DynamicExpressionParser.ParseLambda(new[] {
                    Expression.Parameter(entityType, "u") }, typeof(bool), $"@0.Contains(u.{nameof(EntityBaseData.OrgId)}??{default(long)})", orgIds);
                    db.QueryFilter.AddTableFilter(entityType, lambda);
                    orgFilter.TryAdd(entityType, lambda);
                }
                _cache.Add(cacheKey, orgFilter);
            }
            else
            {
                foreach (var filter in orgFilter)
                    db.QueryFilter.AddTableFilter(filter.Key, filter.Value);
            }
        }

        /// <summary>
        /// 配置用户仅本人数据过滤器
        /// </summary>
        private static int SetDataScopeFilter(SqlSugarScopeProvider db)
        {
            var maxDataScope = (int)DataScopeEnum.All;

            var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value;
            if (string.IsNullOrWhiteSpace(userId)) return maxDataScope;

            // 获取用户最大数据范围---仅本人数据
            maxDataScope = App.GetService<SysCacheService>().Get<int>(CacheConst.KeyRoleMaxDataScope + userId);
            if (maxDataScope != (int)DataScopeEnum.Self) return maxDataScope;

            // 配置用户数据范围缓存
            var cacheKey = $"db:{db.CurrentConnectionConfig.ConfigId}:dataScope:{userId}";
            var dataScopeFilter = _cache.Get<ConcurrentDictionary<Type, LambdaExpression>>(cacheKey);
            if (dataScopeFilter == null)
            {
                // 获取业务实体数据表
                var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
                    && u.IsSubclassOf(typeof(EntityBaseData)));
                if (!entityTypes.Any()) return maxDataScope;

                dataScopeFilter = new ConcurrentDictionary<Type, LambdaExpression>();
                foreach (var entityType in entityTypes)
                {
                    // 排除非当前数据库实体
                    var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
                    if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()))
                        continue;

                    var lambda = DynamicExpressionParser.ParseLambda(new[] {
                    Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId);
                    db.QueryFilter.AddTableFilter(entityType, lambda);
                    dataScopeFilter.TryAdd(entityType, lambda);
                }
                _cache.Add(cacheKey, dataScopeFilter);
            }
            else
            {
                foreach (var filter in dataScopeFilter)
                    db.QueryFilter.AddTableFilter(filter.Key, filter.Value);
            }
            return maxDataScope;
        }

        /// <summary>
        /// 配置自定义过滤器
        /// </summary>
        public static void SetCustomEntityFilter(SqlSugarScopeProvider db)
        {
            // 配置自定义缓存
            var cacheKey = $"db:{db.CurrentConnectionConfig.ConfigId}:custom";
            var tableFilterItemList = _cache.Get<List<TableFilterItem<object>>>(cacheKey);
            if (tableFilterItemList == null)
            {
                // 获取自定义实体过滤器
                var entityFilterTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass
                    && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(IEntityFilter))));
                if (!entityFilterTypes.Any()) return;

                var tableFilterItems = new List<TableFilterItem<object>>();
                foreach (var entityFilter in entityFilterTypes)
                {
                    var instance = Activator.CreateInstance(entityFilter);
                    var entityFilterMethod = entityFilter.GetMethod("AddEntityFilter");
                    var entityFilters = ((IList)entityFilterMethod?.Invoke(instance, null))?.Cast<object>();
                    if (entityFilters == null) continue;

                    foreach (var u in entityFilters)
                    {
                        var tableFilterItem = (TableFilterItem<object>)u;
                        var entityType = tableFilterItem.GetType().GetProperty("type", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tableFilterItem, null) as Type;
                        // 排除非当前数据库实体
                        var tAtt = entityType.GetCustomAttribute<TenantAttribute>();
                        if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()) ||
                            (tAtt == null && db.CurrentConnectionConfig.ConfigId.ToString() != SqlSugarConst.MainConfigId))
                            return;

                        tableFilterItems.Add(tableFilterItem);
                        db.QueryFilter.Add(tableFilterItem);
                    }
                }
                _cache.Add(cacheKey, tableFilterItems);
            }
            else
            {
                tableFilterItemList.ForEach(u =>
                {
                    db.QueryFilter.Add(u);
                });
            }
        }
    }

    /// <summary>
    /// 自定义实体过滤器接口
    /// </summary>
    public interface IEntityFilter
    {
        /// <summary>
        /// 实体过滤器
        /// </summary>
        /// <returns></returns>
        IEnumerable<TableFilterItem<object>> AddEntityFilter();
    }
}
